//////////////////////////////////////////////////////////////////////
////                                                              ////
////  FlashROM.v                                                  ////
////                                                              ////
////                                                              ////
////  This file is part of the "Pico E12" project                 ////
////  http://wwww.picocomputing.com                               ////
////                                                              ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2005, Pico Computing, INC.                     ////
//// http://www.picocomputing.com                                 ////
////                                                              ////
////////////////////////////////////////////////////////////////////JF

//This module manages transfers to and from the FlashROM
//This module attaches to the lower 64MB of the memory address bus

//By default the ROM is in read mode to which allows pre-emptive addressing for a substantial speed increase
`include "PicoDefines.v"
	  
module FlashROM(CFClock, MemRead, MemWrite, DataIn, DataOut, MemAddress, ByteMode, CPLD_PEEKABOO_CF, CPLD_PEEKABOO_PPC,
                FLASH_CE, FLASH_OE, FLASH_WE, FLASH_WP, FLASH_TRIS_D, FLASH_TRIS_D15, FLASH_BYTE, FLASH_DIN, FLASH_DOUT, FLASH_AOUT,
                FLASH_AOUT_NEG_ONE, Wait);

														
input CFClock;                                                                    //200 MHz free running CFClock						   
input MemRead;                                                                    //Read from Card
input MemWrite;                                                                   //Write to Card
input [15:0]DataIn;                                                               //Data in from host
output [15:0]DataOut;                                                             //Data out to host
input [31:0]MemAddress;                                                           //Memory address bus
input ByteMode;                                                                   //8 Bit data mode
input CPLD_PEEKABOO_CF;
input CPLD_PEEKABOO_PPC;
output FLASH_CE;                                                                  //ROM Chip Enable
output FLASH_OE;                                                                  //ROM Output Enable
output FLASH_WE;                                                                  //ROM Write Enable
output FLASH_WP;                                                                  //ROM Write Protect
output FLASH_BYTE;                                                                //ROM 8 Bit Mode Select
output FLASH_TRIS_D;                                                              //FLASH D0-14 Tristate Control
output FLASH_TRIS_D15;                                                            //FLASH D15 Tristate Control
input [15:0]FLASH_DIN;                                                            //FLASH -> FPGA
output [15:0]FLASH_DOUT;                                                          //FLASH <- FPGA
output [25:0]FLASH_AOUT;                                                          //FLASH ROM Address Bus
output FLASH_AOUT_NEG_ONE;                                                        //-1 Address Pin (For 8 bit mode)
output Wait;                                                                      //Delay trasfer until the ROM is ready

wire AddressValid;
wire FlashRead;
wire FlashWrite;
wire WaitInProgress;
wire [7:0]RomDataMSBsMux;

//Basic Address Decoding and Operation Detection
assign AddressValid = (~(|MemAddress[31:26]));                                    //If any of the upper 5 address bits are high then the ROM is not selected
assign FlashRead = (MemRead) && (AddressValid);                                   //Read from ROM
assign FlashWrite = (MemWrite) && (AddressValid);                                 //Write to ROM

 
//Status and Address
assign FLASH_CE = (~FlashRead) && (~FlashWrite);                                  //Flash ROM should always be enabled
assign FLASH_OE = (~FlashRead);                                                   //Flash -> FPGA when Low
assign FLASH_WE = (~FlashWrite);                                                  //Flash <- FPGA when Low																								
assign FLASH_WP = 1'b1;                                                           //Disable hardware write protect
assign FLASH_BYTE = (~ByteMode);                                                  //Support for 8 bit transfers 
assign FLASH_AOUT[25:0] = MemAddress[26:1];                                       //The LSB address is actually D15 in Byte Mode
assign FLASH_AOUT_NEG_ONE = MemAddress[0];

assign Wait = (WaitInProgress && FlashRead);

ShortFallingDelay ShortFallingDelay_FLASH_TRISD(.Clock(CFClock), .In(~FLASH_OE), .Out(FLASH_TRIS_D));
ShortFallingDelay ShortFallingDelay_FLASH_TRISD15(.Clock(CFClock), .In((~FLASH_OE) && FLASH_BYTE | CPLD_PEEKABOO_CF | CPLD_PEEKABOO_PPC), .Out(FLASH_TRIS_D15));

//Host -> ROM
assign FLASH_DOUT[15] = (ByteMode)?MemAddress[0] : DataIn[15];                    //Data Bit 15 gets a little strange for byte mode
assign FLASH_DOUT[14:0] = (DataIn[14:0]);                                         //Luckily D14->0 are normal

									 
//ROM -> Host
assign RomDataMSBsMux[7:0] = (ByteMode)?FLASH_DIN[7:0] : FLASH_DIN[15:8];         //In 8 bit mode dump the LSBs on both the high and low order bytes
assign DataOut[15:8] = (FlashRead)?RomDataMSBsMux[7:0] : 8'b0;                    //The MSBs of DataOut get a little tricky in 8 bit mode when they are a mirror of the FLASH_DATA LSBs
assign DataOut[7:0] = (FlashRead)?FLASH_DIN[7:0] : 8'b0;

//Wait Timer                                                                      //The wait timer delay a Compact Flash Read until the ROM has had enough time to access the data
FlashWaitTimer FlashWaitTimer(.CFClock(CFClock), .FLASH_OE(FLASH_OE), .FLASH_CE(FLASH_CE), .Wait(WaitInProgress));

endmodule